﻿#region Copyright

// All Material Copyright © 2010 Dynamic Concepts Development Corp., All Rights Reserved.
//      Portions Copyright © 1984-2009 Dynamic Concepts Development Corp., All Rights Reserved.
// For further information please contact: SoftwareSupport@dynconcepts.com
// Dynamic Concepts Development Corp.  311 W 57th St. Suite #422, New York, NY 10019

#endregion

#region Using References

using System;
using System.Threading;
using DynConDevCorp.OpenArch.SupportLibrary.ParallelExecution.Events;

#endregion

namespace DynConDevCorp.OpenArch.Samples.CrossThreadExecutionSample
{
    internal class Program
    {
        #region Private Methods

        private static void Main(string[] args)
        {
            Sample sample = new Sample();
            sample.Run();
        }

        #endregion
    }

    public class Sample
    {
        #region Public Methods

        public void Run()
        {
            Thread.CurrentThread.Name = "Main Application Thread";
            SampleEvent1.Add(Handler0);
            ThreadInitialization threadInitialization = new ThreadInitialization();
            threadInitialization.Thread1Initialization += Thread1Initialization;
            threadInitialization.Thread2Initialization += Thread2Initialization;
            threadInitialization.Execute();
            SampleEvent1.Execute(this, new EventArgs());
        }

        #endregion

        #region Private Methods

        private void Handler0(Object sender, EventArgs args)
        {
            Console.WriteLine("Handler0 Invoked on Thread: {0}", Thread.CurrentThread.Name);
            Thread.Sleep(TimeSpan.FromSeconds(0.1)); // Simulate Processing Time
        }

        private void Handler1(Object sender, EventArgs args)
        {
            Console.WriteLine("Handler1 Invoked on Thread: {0}", Thread.CurrentThread.Name);
            Thread.Sleep(TimeSpan.FromSeconds(0.1)); // Simulate Processing Time
        }

        private void Handler2(Object sender, EventArgs args)
        {
            Console.WriteLine("Handler2 Invoked on Thread: {0}", Thread.CurrentThread.Name);
            Thread.Sleep(TimeSpan.FromSeconds(0.1)); // Simulate Processing Time
            SampleEvent2Impl.Execute(this, new EventArgs()); // NOTE: Must execute the "real" handler, not the wrapper
        }

        private void Handler3(Object sender, EventArgs args)
        {
            Console.WriteLine("Handler3 Invoked on Thread: {0}", Thread.CurrentThread.Name);
            Thread.Sleep(TimeSpan.FromSeconds(0.1)); // Simulate Processing Time
        }

        private void Handler4(Object sender, EventArgs args)
        {
            Console.WriteLine("Handler3 Invoked on Thread: {0}", Thread.CurrentThread.Name);
            Thread.Sleep(TimeSpan.FromSeconds(0.1)); // Simulate Processing Time
        }

        private void Thread1Initialization(object sender, EventArgs e)
        {
            Console.WriteLine("{0} Initialized", Thread.CurrentThread.Name);
            SampleEvent1.Add(Handler1);
            SampleEvent2 += Handler3; // NOTE: Wrapper allows "conventional syntax" for callers
        }

        private void Thread2Initialization(object sender, EventArgs e)
        {
            Console.WriteLine("{0} Initialized", Thread.CurrentThread.Name);
            SampleEvent1.Add(Handler2);
            SampleEvent2 += Handler4; // NOTE: Wrapper allows "conventional syntax" for callers
        }

        #endregion

        #region Private Events

        private event EventHandler<EventArgs> SampleEvent2 // NOTE: Wrapper allows "conventional syntax" for callers
        {
            add { SampleEvent2Impl.Add(value); }
            remove { SampleEvent2Impl.Remove(value); }
        }

        #endregion

        #region Instance Fields (ReadOnly)

        private readonly ParallelEvent<EventArgs> SampleEvent1 = new ParallelEvent<EventArgs>();
        private readonly ParallelEvent<EventArgs> SampleEvent2Impl = new ParallelEvent<EventArgs>();

        #endregion

    }
}